﻿#pragma once
#include <fstream>
#include <iostream>
#include "types.hpp"

static const std::string MAGIC_HEADER = "MODBUS_SIM_V1";

class DataPersistence {
public:
    static bool saveToFile(const std::string& filename, const PersistenceData& data) {
        std::ofstream file(filename, std::ios::binary);
        if (!file) {
            std::cerr << "无法打开文件进行写入: " << filename << std::endl;
            return false;
        }

        // 写入魔数头
        file.write(MAGIC_HEADER.c_str(), MAGIC_HEADER.size());

        // 写入时间戳
        uint32_t timestamp = data.timestamp;
        file.write(reinterpret_cast<const char*>(&timestamp), sizeof(timestamp));

        // 写入从站数量
        uint32_t slave_count = static_cast<uint32_t>(data.slaves.size());
        file.write(reinterpret_cast<const char*>(&slave_count), sizeof(slave_count));

        for (const auto& [slave_id, config] : data.slaves) {
            // 写入从站ID
            file.write(reinterpret_cast<const char*>(&slave_id), sizeof(slave_id));

            // 写入线圈数据
            uint32_t coils_size = static_cast<uint32_t>(config.data.coils.size());
            file.write(reinterpret_cast<const char*>(&coils_size), sizeof(coils_size));
            for (bool coil : config.data.coils) {
                uint8_t coil_byte = coil ? 1 : 0;
                file.write(reinterpret_cast<const char*>(&coil_byte), sizeof(coil_byte));
            }

            // 写入离散输入数据
            uint32_t discrete_size = static_cast<uint32_t>(config.data.discrete_inputs.size());
            file.write(reinterpret_cast<const char*>(&discrete_size), sizeof(discrete_size));
            for (bool discrete : config.data.discrete_inputs) {
                uint8_t discrete_byte = discrete ? 1 : 0;
                file.write(reinterpret_cast<const char*>(&discrete_byte), sizeof(discrete_byte));
            }

            // 写入保持寄存器数据
            uint32_t holding_size = static_cast<uint32_t>(config.data.holding_registers.size());
            file.write(reinterpret_cast<const char*>(&holding_size), sizeof(holding_size));
            file.write(reinterpret_cast<const char*>(config.data.holding_registers.data()),
                holding_size * sizeof(uint16_t));

            // 写入输入寄存器数据
            uint32_t input_size = static_cast<uint32_t>(config.data.input_registers.size());
            file.write(reinterpret_cast<const char*>(&input_size), sizeof(input_size));
            file.write(reinterpret_cast<const char*>(config.data.input_registers.data()),
                input_size * sizeof(uint16_t));
        }

        return file.good();
    }

    static bool loadFromFile(const std::string& filename, PersistenceData& data) {
        std::ifstream file(filename, std::ios::binary);
        if (!file) {
            std::cerr << "无法打开文件进行读取: " << filename << std::endl;
            return false;
        }

        // 验证魔数头
        std::vector<char> header(MAGIC_HEADER.size());
        file.read(header.data(), header.size());
        if (std::string(header.data(), header.size()) != MAGIC_HEADER) {
            std::cerr << "无效的文件格式" << std::endl;
            return false;
        }

        // 读取时间戳
        file.read(reinterpret_cast<char*>(&data.timestamp), sizeof(data.timestamp));

        // 读取从站数量
        uint32_t slave_count;
        file.read(reinterpret_cast<char*>(&slave_count), sizeof(slave_count));

        data.slaves.clear();
        for (uint32_t i = 0; i < slave_count; ++i) {
            uint8_t slave_id;
            file.read(reinterpret_cast<char*>(&slave_id), sizeof(slave_id));

            SlaveConfig config;
            config.slave_id = slave_id;

            // 读取线圈数据
            uint32_t coils_size;
            file.read(reinterpret_cast<char*>(&coils_size), sizeof(coils_size));
            config.data.coils.resize(coils_size);
            for (uint32_t j = 0; j < coils_size; ++j) {
                uint8_t coil_byte;
                file.read(reinterpret_cast<char*>(&coil_byte), sizeof(coil_byte));
                config.data.coils[j] = (coil_byte != 0);
            }

            // 读取离散输入数据
            uint32_t discrete_size;
            file.read(reinterpret_cast<char*>(&discrete_size), sizeof(discrete_size));
            config.data.discrete_inputs.resize(discrete_size);
            for (uint32_t j = 0; j < discrete_size; ++j) {
                uint8_t discrete_byte;
                file.read(reinterpret_cast<char*>(&discrete_byte), sizeof(discrete_byte));
                config.data.discrete_inputs[j] = (discrete_byte != 0);
            }

            // 读取保持寄存器数据
            uint32_t holding_size;
            file.read(reinterpret_cast<char*>(&holding_size), sizeof(holding_size));
            config.data.holding_registers.resize(holding_size);
            file.read(reinterpret_cast<char*>(config.data.holding_registers.data()),
                holding_size * sizeof(uint16_t));

            // 读取输入寄存器数据
            uint32_t input_size;
            file.read(reinterpret_cast<char*>(&input_size), sizeof(input_size));
            config.data.input_registers.resize(input_size);
            file.read(reinterpret_cast<char*>(config.data.input_registers.data()),
                input_size * sizeof(uint16_t));

            data.slaves[slave_id] = config;
        }

        return file.good();
    }
};
